#ifndef __IMAGE_PROCESSOR_H__
#define __IMAGE_PROCESSOR_H__

#include <atomic>
#include <mutex>

#include "libhv/json.hpp"
#include "params_setting.h"
#include "preprocessor.h"
#include "postprocessor.h"

enum ShotsCountType {
    TAKEN_COUNT,
    STACKED_COUNT,
    ALL_COUNT
};

enum LightDisplaySource {
    STACKED,
    SINGLE
};

class ImageProcessor {
private:
    FileManager file_manager_;
    Preprocessor preprocessor_;
    Postprocessor postprocessor_;

    std::queue<std::string> img_name_queue_;
    
    std::atomic<bool> b_live_stacking = false;

    const std::string img_stacked_name_ = "/stacked.jpg";
    const std::string shots_info_json_name_ = "/shotsInfo.json";

    static std::atomic<int> capture_light_display_source_;

    // 用于同步APP进度，获取时保证线程安全
    std::atomic<int> stack_count_ = 0;
    int img_to_take_ = 0;
    int exp_setting_index_ = 0;
    int gain_setting_index_ = 0;
    std::string target_name_;

public:
    const std::string dark_folder_ = "/userdata/dark/";

private:
    int sem_timedwait_millsecs(sem_t *sem, long msecs);
    void initLiveStackingImg(const cv::Mat& img_new, cv::Mat& img_stack_all, cv::Mat& img_stack_counter);

public:
    void addImg(const std::string& img_name);
    void popAllImg();
    int startLiveStackingPipeline(int img_to_take, const ExposureSetting& exp_setting, const IntValueSetting& gain_setting, int binning, const std::string& img_parent_path, nlohmann::json& shots_info, std::mutex& shots_info_mutex);
    int startLiveStackingSunMoonPipeline(int img_to_take, const ExposureSetting& exp_setting, const IntValueSetting& gain_setting, int binning, const std::string& img_parent_path, nlohmann::json& shots_info, std::mutex& shots_info_mutex);
    int startLiveStackingPipeline(int img_to_take, const std::string& img_parent_path, double exp, int gain, int binning);
    void stopLiveStacking();

    inline void setCaptureLightDisplaySource(int capture_light_display_source) { capture_light_display_source_ = capture_light_display_source; }
    inline int getCaptureLightDisplaySource() { return capture_light_display_source_; }

    inline int getCaptureLightStackCount() { return stack_count_; }

    void setAndNotifyStackCount(int stack_count);
    void notifyStackCount();
};

#endif